CKYC Validation API
This document highlights the CKYC Validation API details.
Table of Contents
- Objective
- Benefits
- Details
- API URL
- Authentication
- API Request Details
- Inputs
- Request
- Success Response
- Failure Response Samples
- Error Responses
Objective
The CKYC Validation API verifies a user's personally identifiable information (PII) downloaded from their record in the central KYC registry and classifies the response into the following three buckets based on an internal scoring mechanism.
- Approve
- Review
- Reject
| Input | Output |
|---|---|
| The record of the user from the central KYC registry - the user's selfie, XML file, and officially valid documents. | The classification result after matching the user's details across all of these files. |
Benefits
The API verifies the user's PII stored in an XML file in the central KYC registry against their officially valid documents (OVDs) downloaded from the same record. It also verifies if the selfie from the record matches the images present in each OVD file.
A Central KYC Registry record consists of a user's PII in an XML file, a selfie and officially valid documents (OVDs) such as Aadhaar, voter ID, passport and driving license in a PDF file. HyperVerge's identity solution supports any of these four OVDs.
You are expected to parse the XML from a user's central KYC registry record, and send the data to the CKYC Validation API along with the selfie and the OVDs downloaded from the same record.
Details
Scoring Mechanism
The following table describes the score for each field in the document where there is a mismatch.

For each document, the sum of scores is taken and the minimum document score is considered.
Consider a CKYC X instance where the following discrepancies are present:
- The Aadhaar document contains an address error.
- The driving licence document has both a pincode error and an address error.
In this scenario, the scoring is as follows:
- The total score for the Aadhaar document is 2 (with an address error weighted at 2).
- The total score for the driving licence document is 3 (with the pincode error weighted at 1 and the address error weighted at 2).
Consequently, the CKYC X instance's final score will be determined by the Aadhaar document, which has the lowest score of 2 in comparison to the scores of other documents.
API URL
https://ind-ckyc.hyperverge.co/api/v1/validate
Authentication
You need a unique pair of application ID ( appId ) and application key (appKey) from HyperVerge to verify your identity for accessing the API.
API Request Details
Method - POST
Headers
| Parameter | Mandatory or Optional | Type | Description | Valid Values |
|---|---|---|---|---|
content-type | Mandatory | string | This parameter defines the media type for the request payload. | multipart/form-data |
appId | Mandatory | string | The application ID shared by HyperVerge | Not Applicable - this is a unique value. |
appKey | Mandatory | string | The application key shared by HyperVerge | Not Applicable - this is a unique value. |
transactionId | Mandatory | string | Any unique ID. | Not Applicable - this is a unique value. |
Inputs
| Parameter | Mandatory or Optional | Type | Valid Values | Description | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
first_name | Optional | string | Not applicable | The first name of the user. | ||||||||||||||
middle_name | Optional | string | Not applicable | The middle name of the user. | ||||||||||||||
last_name | Optional | string | Not applicable | The last name of the user. | ||||||||||||||
full_name | Optional | string | Not applicable | The full name of the user. | ||||||||||||||
dob | Optional | string | Not applicable | The date of birth of the user in the format DD-MM-YYYY. | ||||||||||||||
address1 | Optional | string | Not applicable | The primary address line of the user. | ||||||||||||||
address2 | Optional | string | Not applicable | The secondary address line of the user. | ||||||||||||||
address3 | Optional | string | Not applicable | The tertiary address line of the user. | ||||||||||||||
city | Optional | string | Not applicable | The city of residence of the user. | ||||||||||||||
district | Optional | string | Not applicable | The district of residence of the user. | ||||||||||||||
state | Optional | string | Not applicable | The state of residence of the user. | ||||||||||||||
country | Optional | string | Not applicable | The country of residence of the user. | ||||||||||||||
pincode | Optional | string | Not applicable | The PIN code or postal code of residence of the user. | ||||||||||||||
aadhaar | Selectively Optional: The request should have at least one of the following inputs:
| string | Not applicable | The Aadhaar number of the user. | ||||||||||||||
driving_license | Selectively Optional: The request should have at least one of the following inputs:
| string | Not applicable | The driving license number of the user. | ||||||||||||||
voter_id | Selectively Optional: The request should have at least one of the following inputs:
| string | Not applicable | The voter ID number of the user. | ||||||||||||||
passport | Selectively Optional: The request should have at least one of the following inputs:
| string | Not applicable | The passport number of the user. | ||||||||||||||
pan | Optional | string | Not applicable | The PAN number of the user. | ||||||||||||||
validate_pan | Optional | string | "yes" or "no" | Indicates whether to validate the PAN number. | ||||||||||||||
mask_aadhaar | Optional | string | "yes" or "no" | Indicates whether to mask the Aadhaar number. | ||||||||||||||
image_details | Selectively Optional* This parameter becomes mandatory if the | file |
| The image file(s) containing the supporting documents of the user. These will be validated against the input fields in the request. You can also include a file with the image of the user to perform a face match identity authentication. Alternatively, this parameter can be passed as received from the | ||||||||||||||
imageDetails | Selectively Optional* This parameter becomes mandatory if the | object | Object with valid image URL strings | This parameter allows to send images using urls with acceptable document code. The details obtained from the search and download response, including the code of the kyc document and the url containing the image or the pdf | ||||||||||||||
returnOcrDump | Optional | string | "yes" or "no" | If set to 'yes', the response has an additional ocrDump field. It contains a combined string with characters extracted from each file attached to the API request using Optical Character Recognition (OCR). | ||||||||||||||
standardOcrDump | Optional | string | "yes" or "no" | If set to 'yes', the response has an additional ocrDump field. It contains a combined string with characters extracted from each file attached to the API request using Optical Character Recognition (OCR). | ||||||||||||||
returnMaskedAadhaarNumber | Optional | string | "yes" or "no" | If set to "yes", the user's Aadhaar value is masked in the response. | ||||||||||||||
returnInputImage | Optional | string | "yes" or "no" | If set to "yes", the response will include a key inputImageUrls, which contains the URLs of the input files. | ||||||||||||||
returnSingleMaskedFile | Selectively Optional* This parameter becomes works only when mask_aadhaar parameter is enabled. | string | "yes" or "no" | If set to "yes", the response will include a key masked_aadhaar_url, containing a single merged file of the masked Aadhaar documents. If not enabled, the masked files will be returned as individual, unmerged documents by default. |
Request
The following code shows a standard curl request for the API.
curl --location --request POST 'https://ind-ckyc.hyperverge.co/api/v1/validate' \
--header 'Content-Type: multipart/form-data' \
--header 'appId: <Enter_the_HyperVerge_appId>' \
--header 'appKey: <Enter_the_HyperVerge_appKey>' \
--header 'transactionId: <Enter_the_HyperVerge_transactionID>' \
--form 'first_name="<Enter_the_firstName>"' \
--form 'last_name="<Enter_the_lastName>"' \
--form 'dob="<Enter_the_DD-MM-YYYY>"' \
--form 'address1="<Enter_the_address1>"' \
--form 'address2="<Enter_the_address2>"' \
--form 'address3="<Enter_the_address3>"' \
--form 'city="<Enter_the_city>"' \
--form 'district="<Enter_the_district>"' \
--form 'state="<Enter_the_state>"' \
--form 'country="<Enter_the_country>"' \
--form 'pincode="<Enter_the_pincode>"' \
--form 'mask_aadhaar="<Enter_yes_or_no>"' \
--form 'image_details=@"<Enter_the_path_to_file>"' \
--form 'image_details=@"<Enter_the_path_to_file>"' \
--form 'image_details=@"<Enter_the_path_to_file>"' \
--form 'pan="<Enter_the_pan>"' \
--form 'validate_pan="<Enter_yes_or_no>"' \
--form 'aadhaar="<Enter_the_aadhaar>"' \
--form 'standardOcrDump="<Enter_yes_or_no>"' \
--form 'returnOcrDump="<Enter_yes_or_no>"'
Success Response
The following is the structure of a successful response from the API.
{
"status": "success",
"statusCode": 200,
"result": {
"action": "String",
"validPOA": ["String"],
"validPOI": ["String"],
"invalidDocs": {
"document": ["error"]
},
"details": {
"document": {
"field": {
"matchFound": true,
"score": 0
}
}
},
"masked_aadhaar_url": ["String"]
}
}
Success Response Details
The following table provides the details of the fields in a success response.
| Parameter | Type | Valid Values | Description |
|---|---|---|---|
action | - | approve, reject, manual_review |
|
validPOA | - | "passport", "aadhaar", "voter_id", "dl", "pan", "other", "photo", "aadhaar_kyc" | Lists all the documents that have succeeded address validation |
validPOI | - | "passport", "aadhaar", "voter_id", "dl", "pan", "other", "photo", "aadhaar_kyc" | Lists all the documents that have succeeded identity validation such as name and face match |
invalidDocs | - | Contains a map of the document with the mismatch codes. Valid documents include Aadhaar, passport, driving_license and voter_id. | |
details | Object document, Object field, matchFound: boolean, score: number. |
| |
masked_aadhaar_url | Array of Strings | Not Applicable | The link to the user's masked Aadhaar image with the first 8 digits masked. It is valid for 15 mins. |
Success Responses
If the status is "success" in the response, the CKYC validation process is complete.
The following samples reflect scenarios where the action field is "approve".
- Success - With Aadhaar Type Parameter
- Basic Response
- Includes Doc Template Field
- Includes StandardOCRDump Object
The record is approved when all the fields are validated and the total score is less than 2.
{
"status": "success",
"statusCode": "200",
"result": {
"action": "approve",
"validPOA": ["aadhaar"],
"validPOI": ["aadhaar"],
"invalidDocs": {},
"details": {
"aadhaar": {
"first_name": {
"matchFound": true,
"score": 90
},
"last_name": {
"matchFound": true,
"score": 100
},
"address1": {
"matchFound": true,
"score": 95
},
"address2": {
"matchFound": true,
"score": 96
},
"address3": {
"matchFound": true,
"score": 100
},
"city": {
"matchFound": true,
"score": 100
},
"dob": {
"matchFound": true,
"score": 100
},
"aadhaar": {
"matchFound": true,
"score": 100
},
"faceMatch": {
"matchFound": true,
"score": 90
}
}
},
"aadhaar_type": "STANDARD"
}
}
If the mask_aadhaar parameter is set "yes" in the request, the masked_aadhaar_url returns a URL with the user's masked aadhaar.
{
"status": "success",
"statusCode": "200",
"result": {
"action": "approve",
"validPOA": ["aadhaar"],
"validPOI": ["aadhaar"],
"invalidDocs": {},
"details": {
"aadhaar": {
"first_name": {
"matchFound": true,
"score": 90
},
"last_name": {
"matchFound": true,
"score": 100
},
"address1": {
"matchFound": true,
"score": 95
},
"address2": {
"matchFound": true,
"score": 96
},
"address3": {
"matchFound": true,
"score": 100
},
"city": {
"matchFound": true,
"score": 100
},
"dob": {
"matchFound": true,
"score": 100
},
"aadhaar": {
"matchFound": true,
"score": 100
},
"faceMatch": {
"matchFound": true,
"score": 90
}
}
},
"aadhaar_type": "STANDARD",
"masked_aadhaar_url": ["<URL>"]
}
}
{
"status": "success",
"statusCode": "200",
"result": {
"action": "approve",
"validPOA": ["aadhaar"],
"validPOI": ["aadhaar"],
"invalidDocs": {},
"details": {
"aadhaar": {
"first_name": {
"matchFound": true,
"score": 90
},
"last_name": {
"matchFound": true,
"score": 100
},
"address1": {
"matchFound": true,
"score": 95
},
"address2": {
"matchFound": true,
"score": 96
},
"address3": {
"matchFound": true,
"score": 100
},
"city": {
"matchFound": true,
"score": 100
},
"dob": {
"matchFound": true,
"score": 100
},
"aadhaar": {
"matchFound": true,
"score": 100
},
"faceMatch": {
"matchFound": true,
"score": 90
},
"doc_template": ["aadhaar_front_bottom", "aadhaar_back"]
}
},
"aadhaar_type": "STANDARD"
}
}
{
"standardOcrDump": {
"aadhaar": [
{
"type": "aadhaar_front_bottom",
"details": {
"name": {
"conf": 99,
"value": "<User_Name>"
},
"gender": {
"conf": 95,
"value": "<User_Gender>"
},
"yob": {
"conf": 0,
"value": "<User_YOB>"
},
"dob": {
"conf": 90,
"value": "<User_DOB>"
},
"aadhaar": {
"conf": 90,
"value": "<User_Aadhaar_Number>",
"ismasked": "<IsMasked_Flag>"
},
"father": {
"conf": 0,
"value": "<User_Father_Name>"
},
"mother": {
"conf": 0,
"value": "<User_Mother_Name>"
},
"tag": "<Tag_ID>",
"qr": {
"value": "<QR_Value>"
},
"face": {
"present": "<Face_Present>",
"faceString": "<Face_String>"
}
}
},
{
"type": "aadhaar_back",
"details": {
"aadhaar": {
"conf": 90,
"value": "<User_Aadhaar_Number>",
"ismasked": "<IsMasked_Flag>"
},
"address": {
"conf": 45,
"value": "<User_Address>",
"city": "<City_Name>",
"pin": "<Pin_Code>",
"line1": "<Address_Line1>",
"line2": "<Address_Line2>",
"care_of": "<Care_Of>",
"state": "<State_Name>",
"locality": "<Locality_Name>",
"landmark": "<Landmark_Name>",
"house_number": "<House_Number>",
"street": "<Street_Name>",
"district": "<District_Name>"
},
"father": {
"conf": 0,
"value": "<User_Father_Name>"
},
"husband": {
"conf": 45,
"value": "<User_Husband_Name>"
},
"pin": {
"conf": 90,
"value": "<Pin_Code>"
},
"tag": "<Tag_ID>",
"qr": {
"value": "<QR_Value>"
},
"face": {
"present": "<Face_Present>",
"faceString": "<Face_String>"
}
}
}
]
}
}
Failure Response Samples
Explore failure response scenarios where the 'action' is either 'manual review' or 'reject'.
- Failure Response Sample - Reject Channel
- Failure Response Sample - Manual Review Channel
{
"status": "success",
"statusCode": "200",
"result": {
"action": "reject",
"validPOA": [],
"validPOI": [],
"invalidDocs": {
"dl": ["ER_FACE_NO_MATCH", "ER_NAME"]
},
"details": {
"dl": {
"first_name": {
"matchFound": false,
"score": 40
},
"last_name": {
"matchFound": false,
"score": 60
},
"dob": {
"matchFound": true,
"score": 100
},
"address1": {
"matchFound": true,
"score": 100
},
"address2": {
"matchFound": true,
"score": 100
},
"address3": {
"matchFound": true,
"score": 100
},
"city": {
"matchFound": true,
"score": 100
},
"faceMatch": {
"matchFound": false,
"score": 35
}
}
}
}
}
{
"status": "success",
"statusCode": "200",
"result": {
"action": "manual_review",
"validPOA": ["aadhaar"],
"validPOI": [],
"invalidDocs": {
"aadhaar": ["ER_FACE_NO_MATCH"]
},
"details": {
"aadhaar": {
"first_name": {
"matchFound": true,
"score": 100
},
"last_name": {
"matchFound": true,
"score": 100
},
"address1": {
"matchFound": true,
"score": 100
},
"address2": {
"matchFound": true,
"score": 100
},
"address3": {
"matchFound": true,
"score": 100
},
"city": {
"matchFound": true,
"score": 100
},
"dob": {
"matchFound": true,
"score": 100
},
"aadhaar": {
"matchFound": true,
"score": 100
},
"faceMatch": {
"matchFound": false,
"score": 37
}
}
},
"aadhaar_type": "STANDARD"
}
}
Error Responses
- Sample Error 401
{
"status": "failure",
"statusCode": "401",
"error": "Missing/Invalid credentials"
}
Code property from error object | Category | Description |
|---|---|---|
| ER_BAD_DOC | Bad document | Document is not readable |
| ER_FACE_NO_MATCH | Face mismatch | Face Match not found |
| ER_FACE_MISSING | Face missing | |
| ER_NAME | Field mismatch | The name is a mismatch. |
| ER _ADDRESS | The address is a mismatch. | |
| ER_DOB | The date of birth is a mismatch. | |
| ER_ID | The ID number is a mismatch. | |
| ER_PINCODE | The pin code does not match. | |
| ER_SERVER | File size exceeds the limit | File size exceeds 6MB. |
| ER_SERVER | Document length exceeds the limit | The document exceeds 5 pages. |
| Status Code | Error Message | Description |
|---|---|---|
| 401 | Missing/Invalid credentials | You have either missed to include the appid and appkey credentials in the request header or you have provided incorrect values. |
| 400 | first_name should not be null or undefined | You have missed to send the mandatory parameters in the request. |
| 400 | Selfie image not sent as part of the payload | You have missed to send the selfie image in the request. |
| 400 | pages exceeded the supported length of 5 | The number of pages in the request document exceeds 5 pages. |
| 413 | File too large | This status code is returned for requests with a file size exceeding 6MB. |
| 5xx | Internal server error | This status code is returned for server errors. Kindly reach out to HyperVerge. |
- Error 400 (a)
- Error 400 (b)
- Error 400 (c)
- Error 413
- Error 500
{
"status": "fail",
"statusCode": "400",
"error": {
"code": "ER_REQ_VALIDATE",
"message": "first_name should not be null or undefined"
}
}
{
"status": "failure",
"statusCode": "400",
"error": {
"code": "ER_REQ_VALIDATE",
"message": "Selfie image not sent as part of the payload"
}
}
{
"status": "failure",
"statusCode": "400",
"error": {
"code": "ER_PAGE",
"message": "pages exceeded the supported length of 5"
}
}
{
"status": "failure",
"statusCode": "413",
"error": {
"code": "ER_SERVER",
"message": "File too large"
}
}
{
"status": "failure",
"statusCode": "500",
"error": {
"code": "ER_SERVER",
"message": "Internal server error"
}
}